#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <iomanip>
#include <array>
#include "Var.h"
#include "VarHeader.h"

#if defined (__WIN32__) || defined (__WIN64__)

#include <cstring>
#endif

#if defined (__unix__) || defined (__APPLE__)
#include <cstring>
#define _strcmpi strcasecmp



#endif
// Global definitions
template<typename D, size_t N,typename loop>
void print_arry(const array<D, N> data,loop size) {
  if (!data.empty()) {
    cout << "\t\t data: " << endl;
    cout << "\t\t ";
    for (auto val = data.begin(); val < data.begin() + size; val++) {
      cout << "0x" << setw(sizeof(D)*2) << hex << uppercase << setfill('0') << (uint16_t)(*val) << " ";
      if (!((val + 1 - data.begin()) % 0x10) && (val != data.begin() + size -1) ) {
        cout << "\n\t\t ";
      }
    }
    cout << "\n" << endl;
  }
}

varType getVarType(const string &buffer, string guid) {

	varType currtype = UN_KNOWN;
  EFI_FIRMWARE_VOLUME_HEADER *volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)&buffer[0];
	if (GuidToString(volumeHeader->FileSystemGuid) == guid) {
#ifdef DEBUG
    cout << "is VOLUME_HEADER " << endl;
#endif // DEBUG
    
    currtype = VOLUME_HEADER;
  } else {
#ifdef DEBUG
    cout << "not VOLUME_HEADER " << endl;
#endif // DEBUG
    //
    currtype = STORE_HEADER;
  }
  //
  return currtype;
}

void getVarHeaderInfo( varType type, const string &buffer, vector<EFI_VOLUME_HEADER_PACK> &volumePackages) {
#ifdef DEBUG
  cout << "[" << __FUNCTION__ << "](" << dec << __LINE__ << ") begin." << endl;
#endif // DEBUG
  
  if (type != VOLUME_HEADER) {
    return;
  }
  EFI_VOLUME_HEADER_PACK volumePack;
  EFI_FIRMWARE_VOLUME_HEADER *volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)&buffer[0];
  for (size_t j = 0; j < 16; j++) {
    volumePack.volumeHeader.ZeroVector.at(j) = buffer[j];
  }
  volumePack.volumeHeader.FileSystemGuid = GuidToString(volumeHeader->FileSystemGuid);
  volumePack.volumeHeader.FvLength = volumeHeader->FvLength;
  volumePack.volumeHeader.Signature = volumeHeader->Signature;
  volumePack.volumeHeader.Attributes = volumeHeader->Attributes;
  volumePack.volumeHeader.HeaderLength = volumeHeader->HeaderLength;
  volumePack.volumeHeader.Checksum = volumeHeader->Checksum;
  volumePack.volumeHeader.ExtHeaderOffset = volumeHeader->ExtHeaderOffset;
  volumePack.volumeHeader.Revision = volumeHeader->Revision;
  volumePack.volumeHeader.BlockMap[0].NumBlocks = volumeHeader->BlockMap[0].NumBlocks;
  volumePack.volumeHeader.BlockMap[0].Length = volumeHeader->BlockMap[0].Length;

  volumePack.offset = 0;
  volumePack.size   = volumePack.volumeHeader.HeaderLength;
  if (volumePack.volumeHeader.HeaderLength < volumePack.data.size()) {
    for (size_t i = 0; i < volumePack.volumeHeader.HeaderLength; i++)
    {
      volumePack.data.at(i) = buffer[i];
    }
  } else {
    cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Header size is over!!!" << endl;
  }

  volumePackages.push_back(volumePack);
  //volumePack.volumeHeader.ZeroVector.clear();
  return;
}

void displayVarHeaderInfo(const vector<EFI_VOLUME_HEADER_PACK> &volumePackages) {

  // Display VarHeader info
  cout << "[" << __FUNCTION__ << "](" << dec << __LINE__ << ") begin." << endl;

  // Go through VarHeader
  for (uint32_t i = 0; i < volumePackages.size(); i++) {
    // Display string package info
    cout << "\t volumePackages " << i << " data:" << endl;
    cout << "\t\t offset: 0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].offset << endl;
    cout << "\t\t size:   0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].size << endl;
    print_arry(volumePackages[i].data, volumePackages[i].volumeHeader.HeaderLength);
    cout << "\t volumePackages " << i << " Information:" << endl;
    print_arry(volumePackages[i].volumeHeader.ZeroVector, volumePackages[i].volumeHeader.ZeroVector.size());
    cout << "\t\t FileSystemGuid:  " << volumePackages[i].volumeHeader.FileSystemGuid << endl;
    cout << "\t\t FvLength:        0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.FvLength << endl;
    cout << "\t\t Signature:       0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.Signature << endl;
    cout << "\t\t Attributes:      0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.Attributes << endl;
    cout << "\t\t HeaderLength:    0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.HeaderLength << endl;
    cout << "\t\t Checksum:        0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.Checksum << endl;
    cout << "\t\t ExtHeaderOffset: 0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.ExtHeaderOffset << endl;
    cout << "\t\t Revision:        0x" << setw(8) << hex << uppercase << setfill('0') << (uint16_t)volumePackages[i].volumeHeader.Revision << endl;
    cout << "\t\t NumBlocks:       0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.BlockMap[0].NumBlocks << endl;
    cout << "\t\t Length:          0x" << setw(8) << hex << uppercase << setfill('0') << volumePackages[i].volumeHeader.BlockMap[0].Length << endl;
  }
  cout << endl;
}

void getVarStoreHeaderInfo( varType type, const string &buffer, vector<EFI_VOLUME_HEADER_PACK> &volumePackages, vector<EFI_VARIABLE_STORE_HEADER_PACK> &storePackages) {
#ifdef DEBUG
  cout << "[" << __FUNCTION__ << "](" << dec << __LINE__ << ") begin." << endl;
#endif // DEBUG  
  if (type != VOLUME_HEADER) {
    return;
  }
  EFI_VARIABLE_STORE_HEADER_PACK storePack;

  storePack.offset = volumePackages[0].offset + volumePackages[0].size;
  storePack.size = sizeof(VARIABLE_STORE_HEADER);
  if (storePack.size < storePack.data.size()) {
    for (size_t i = 0; i < storePack.size; i++) {
      storePack.data.at(i) = buffer[i + storePack.offset];
    }
  } else {
    cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Header size is over!!!" << endl;
  }

  VARIABLE_STORE_HEADER *storeHeader = (VARIABLE_STORE_HEADER *)(storePack.data.data());
  storePack.storeHeader.Signature = GuidToString(storeHeader->Signature);
  storePack.storeHeader.Size      = storeHeader->Size;
  storePack.storeHeader.Format    = storeHeader->Format;
  storePack.storeHeader.State     = storeHeader->State;

  storePack.variables.offset      = storePack.offset + storePack.size;
  storePack.variables.size        = storePack.storeHeader.Size - storePack.size;
  if (storePack.variables.size < storePack.variables.data.size()) {
    for (size_t i = 0; i < storePack.variables.size; i++) {
      storePack.variables.data.at(i) = buffer[i + storePack.variables.offset];
    }
  } else {
    cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") variables data size is over!!! " << storePack.variables.size << " -- " << storePack.variables.data.size() << endl;
  } 

  storePackages.push_back(storePack);
  return;
}

void displayVarStoreHeaderInfo(const vector<EFI_VARIABLE_STORE_HEADER_PACK> &storePackages) {
  // Display string packages info
  cout << "[" << __FUNCTION__ << "](" << dec << dec << __LINE__ << ") begin." << endl;
  // Go through string packages
  for (size_t i = 0; i < storePackages.size(); i++) {
    // Display string package info
    cout << "\t storePackages " << i << " data:" << endl;
    cout << "\t\t offset: 0x" << setw(8) << hex << uppercase << setfill('0') << storePackages[i].offset << endl;
    cout << "\t\t size:   0x" << setw(8) << hex << uppercase << setfill('0') << storePackages[i].size << endl;
    print_arry(storePackages[i].data, storePackages[i].size);
    cout << "\t storePackages " << i << " Information:" << endl;
    cout << "\t\t Signature: " << storePackages[i].storeHeader.Signature << endl;
    cout << "\t\t Size:      0x" << setw(8) << hex << uppercase << setfill('0') << storePackages[i].storeHeader.Size << endl;
    cout << "\t\t Format:    0x" << setw(8) << hex << uppercase << setfill('0') << (uint16_t)storePackages[i].storeHeader.Format << endl;
    cout << "\t\t State:     0x" << setw(8) << hex << uppercase << setfill('0') << (uint16_t)storePackages[i].storeHeader.State << endl;

    cout << "\t storePackages " << i << " variables:" << endl;
    cout << "\t\t variables offset: 0x" << hex << uppercase << setfill('0') << storePackages[i].variables.offset << endl;
    cout << "\t\t variables size:   0x" << hex << uppercase << setfill('0') << storePackages[i].variables.size << endl;
    //print_arry(storePackages[i].variables.data, storePackages[i].variables.size);
  }
  cout << endl;
}

#define INVALID_START_ID (0xFFFF)
void getVariableInfo( varType type, const string &buffer, vector<EFI_VOLUME_HEADER_PACK> &volumePackages, \
                    vector<EFI_VARIABLE_STORE_HEADER_PACK> &storePackages,\
                    vector<EFI_VARIABLE_PACK> &variablePackages) {
#ifdef DEBUG
  cout << "[" << __FUNCTION__ << "](" << dec << __LINE__ << ") begin." << endl;
#endif // DEBUG
  if (type != VOLUME_HEADER)
  {
    return;
  }
  EFI_VARIABLE_PACK variablePack;
  for (size_t i = 0; i < storePackages[0].variables.size; i++) {
    //cout << "\r [" << __FUNCTION__ << "](" << dec << __LINE__ << ") loop = " << i << endl;
    if (!i) {
      variablePack.offset = storePackages[0].offset + storePackages[0].size;
    } else {
      variablePack.offset += variablePack.size;
    }
    if (storePackages[0].storeHeader.Signature == GuidToString(*((EFI_GUID *)NVRAM_FDC_STORE_GUID))) {
      variablePack.size = sizeof(VARIABLE_HEADER);
    } else if (storePackages[0].storeHeader.Signature == GuidToString(*((EFI_GUID *)NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID))) {
      variablePack.size = sizeof(AUTH_VARIABLE_HEADER);
    } else {
      cout << "\rERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") No support storeHeader.Signature ! " << endl;
    }
    uint64_t varHeaderLen = variablePack.size;
    
    if (variablePack.size < variablePack.data.size()) {
      for (size_t i = 0; i < variablePack.size; i++)
      {
        variablePack.data.at(i) = buffer[i + variablePack.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Header size is over variablePack.size = 0x" \
                                                                      << setw(8) << hex << uppercase << setfill('0') << variablePack.size << endl;
    }

    if (storePackages[0].storeHeader.Signature == GuidToString(*((EFI_GUID *)NVRAM_FDC_STORE_GUID))) {
      VARIABLE_HEADER *variableHeader = (VARIABLE_HEADER *)(variablePack.data.data());
      variablePack.variableHeader.StartId    = variableHeader->StartId;
      if (variablePack.variableHeader.StartId == INVALID_START_ID) {
        #ifdef DEBUG
        cout << "INFO: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Parase variable finish with Header StartId = 0x" \
                                                                        << setw(8) << hex << uppercase << setfill('0') << variablePack.variableHeader.StartId << endl;
        #endif // DEBUG
        break;
      }
      variablePack.variableHeader.State      = variableHeader->State;
      variablePack.variableHeader.Attributes = variableHeader->Attributes;
      variablePack.variableHeader.NameSize   = variableHeader->NameSize;
      variablePack.variableHeader.DataSize   = variableHeader->DataSize;
      variablePack.variableHeader.VendorGuid = GuidToString(variableHeader->VendorGuid);
    } else if (storePackages[0].storeHeader.Signature == GuidToString(*((EFI_GUID *)NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID))) {
      AUTH_VARIABLE_HEADER *variableHeader = (AUTH_VARIABLE_HEADER *)(variablePack.data.data());
      variablePack.variableHeader.StartId    = variableHeader->StartId;
      if (variablePack.variableHeader.StartId == INVALID_START_ID) {
        #ifdef DEBUG
        cout << "INFO: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Parase variable finish with Header StartId = 0x" \
                                                                        << setw(8) << hex << uppercase << setfill('0') << variablePack.variableHeader.StartId << endl;
        #endif // DEBUG
        break;
      }
      variablePack.variableHeader.State      = variableHeader->State;
      variablePack.variableHeader.Attributes = variableHeader->Attributes;
      variablePack.variableHeader.NameSize   = variableHeader->NameSize;
      variablePack.variableHeader.DataSize   = variableHeader->DataSize;
      variablePack.variableHeader.VendorGuid = GuidToString(variableHeader->VendorGuid);
    } else {
      cout << "\rERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") No support storeHeader.Signature ! " << endl;
    }
    
   if(variablePack.variableHeader.Attributes == 0xffffffff || variablePack.variableHeader.NameSize == 0xffffffff  ||  variablePack.variableHeader.DataSize == 0xffffffff || variablePack.variableHeader.State == 0xff  )
    {
        // There is some thing wrong with this variable.
        // We nead Fix it.
      for (size_t i = 2; i < 0x1000; i++)
      {
        if(  0xaa == (buffer[i + variablePack.offset]&0xff) && 0x55 ==  (buffer[i + 1 + variablePack.offset] &0xff) )
        {
          #ifdef DEBUG
          cout <<"Warning:Correct the Variable Start jump " <<hex<< i <<" Bytes"<<endl;
          #endif // DEBUG
          variablePack.size = i ;
          break;
        }
      }
      variablePack.variableHeader.NameSize= 0;
      variablePack.variableHeader.DataSize= 0;
    }
    else
    {  // normal  variable
        variablePack.size += variablePack.variableHeader.NameSize + variablePack.variableHeader.DataSize;
    }
    if (variablePack.size%4) {
        variablePack.size = (variablePack.size/4 + 1) * 4;
    }
    if (variablePack.size < variablePack.data.size()) {
      for (size_t i = varHeaderLen; i < variablePack.size; i++)
      {
        variablePack.data.at(i) = buffer[i + variablePack.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Header size is over variablePack.size = 0x" \
                                                                      << setw(8) << hex << uppercase << setfill('0') << variablePack.size << endl;
    }

    variablePack.variable.name.offset = variablePack.offset + varHeaderLen;
    variablePack.variable.name.size = variablePack.variableHeader.NameSize;
    variablePack.variable.name.name.clear();
    for (uint32_t j = 0; j <  variablePack.variable.name.size; j++) {
      variablePack.variable.name.name.push_back(buffer[variablePack.variable.name.offset + j]);
    }

    variablePack.variable.data.offset = variablePack.variable.name.offset + variablePack.variable.name.size;
    variablePack.variable.data.size   = variablePack.variableHeader.DataSize;
    if (variablePack.variable.data.size < variablePack.variable.data.data.size()) {
      for (size_t i = 0; i < variablePack.variable.data.size ; i++)
      {
        variablePack.variable.data.data.at(i) = buffer[i + variablePack.variable.data.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") variable data size is over!!!" << endl;
    } 
    variablePackages.push_back(variablePack);
  }
  return;
}

/* 从variable列表中找到对应名字的variable */
bool findVarPack(string var, const vector<EFI_VARIABLE_PACK> &variablePackages, string Guid)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr;
	
	for (index = 0; index < variablePackages.size(); index++)
	{
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		if (Guid != variablePackages[index].variableHeader.VendorGuid)
		{
			continue;
		}

			
		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}
								
		temstr=buf;
			
		if ((!temstr.compare(0, var.size(), var)) && (temstr.size() == var.size()))
		{
			break;
		}
	}

	if (index >= variablePackages.size())
	{  
		return false;
	}

	return true;
}

/* 解析NVAR格式 */
void getNVarInfo(const string &buffer, string NVARGuid,\
                    vector<EFI_VARIABLE_PACK> &variablePackages) {
#ifdef DEBUG
  cout << "[" << __FUNCTION__ << "](" << dec << __LINE__ << ") begin." << endl;
#endif // DEBUG
  EFI_VARIABLE_PACK variablePack;
  EFI_FFS_FILE_HEADER *FFsHeader = (EFI_FFS_FILE_HEADER *)&buffer[0];
  if (GuidToString(FFsHeader->Name) != NVARGuid)
  {
    return;
  }

  uint64_t u64Size = FFsHeader->Size[0] + (FFsHeader->Size[1] << 8) + (FFsHeader->Size[2] << 16);
  uint64_t u64Offset = sizeof(EFI_FFS_FILE_HEADER);
  uint64_t u64deoffset = 0;
  uint64_t u64deSize = 0;
  for (size_t i = 0; i < u64Size;) {
    //cout << "\r [" << __FUNCTION__ << "](" << dec << __LINE__ << ") loop = " << i << endl;
    if (!i) {
      variablePack.offset = u64Offset;
    } else {
      variablePack.offset += variablePack.size;
    }
    
    NVAR_ENTRY_HEADER *NVARHeader = (NVAR_ENTRY_HEADER *)&buffer[variablePack.offset];
    if (NVARHeader->Signature != NVRAM_NVAR_ENTRY_SIGNATURE)
    {
         break;
    }

    variablePack.size = NVARHeader->Size;
    i = variablePack.offset + variablePack.size;

    if (NVARHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY)
    {
        continue;
    }

   
    
    if (variablePack.size < variablePack.data.size()) {
      for (size_t i = 0; i < variablePack.size; i++)
      {
        variablePack.data.at(i) = buffer[i + variablePack.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Header size is over variablePack.size = 0x" \
                                                                      << setw(8) << hex << uppercase << setfill('0') << variablePack.size << endl;
    }
    EFI_GUID *guid = (EFI_GUID *)&buffer[u64Size - 16 * (NVARHeader->u8Index + 1)];
    variablePack.variableHeader.StartId      = 0x55AA;
    variablePack.variableHeader.Attributes = (NVARHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY) ? 0x03:0x07;
    variablePack.variableHeader.NameSize   = strlen(NVARHeader->Name) + 1;
    variablePack.variableHeader.DataSize   = NVARHeader->Size - variablePack.variableHeader.NameSize - sizeof(NVAR_ENTRY_HEADER);
    variablePack.variableHeader.State = 0x3F;
    variablePack.variableHeader.VendorGuid = GuidToString(*guid);

    variablePack.variable.name.offset = variablePack.offset + offsetof(NVAR_ENTRY_HEADER, Name);
    variablePack.variable.name.size = variablePack.variableHeader.NameSize * 2;
    variablePack.variable.name.name.clear();
    for (uint32_t j = 0; j <  variablePack.variable.name.size/2; j++) {
      variablePack.variable.name.name.push_back(buffer[variablePack.variable.name.offset + j]);
      variablePack.variable.name.name.push_back(0x0);
    }

    variablePack.variable.data.offset = variablePack.variable.name.offset + variablePack.variableHeader.NameSize;
    variablePack.variable.data.size   = variablePack.variableHeader.DataSize;
    if (variablePack.variable.data.size < variablePack.variable.data.data.size()) {
      for (size_t i = 0; i < variablePack.variable.data.size ; i++)
      {
        variablePack.variable.data.data.at(i) = buffer[i + variablePack.variable.data.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") variable data size is over!!!" << endl;
    } 

    if (0 == strcmp(NVARHeader->Name, "StdDefaults"))
    {
        u64deoffset = variablePack.variable.data.offset;
        u64deSize = variablePack.variable.data.size;
    }

    variablePackages.push_back(variablePack);
  }

  /* 将StdDefaults中的默认值添加到var容器中 */
  for (size_t i = 0; i < u64deSize;) {
    //cout << "\r [" << __FUNCTION__ << "](" << dec << __LINE__ << ") loop = " << i << endl;
    if (!i) {
      variablePack.offset = u64deoffset;
    } else {
      variablePack.offset += variablePack.size;
    }
    
    NVAR_ENTRY_HEADER *NVARHeader = (NVAR_ENTRY_HEADER *)&buffer[variablePack.offset];
    if (NVARHeader->Signature != NVRAM_NVAR_ENTRY_SIGNATURE)
    {
         break;
    }

    variablePack.size = NVARHeader->Size;
    i = variablePack.offset + variablePack.size;

    if (NVARHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY)
    {
        continue;
    }
    
    if (variablePack.size < variablePack.data.size()) {
      for (size_t i = 0; i < variablePack.size; i++)
      {
        variablePack.data.at(i) = buffer[i + variablePack.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") Header size is over variablePack.size = 0x" \
                                                                      << setw(8) << hex << uppercase << setfill('0') << variablePack.size << endl;
    }
    EFI_GUID *guid = (EFI_GUID *)&buffer[u64deoffset + u64deSize - 16 * (NVARHeader->u8Index + 1)];
    variablePack.variableHeader.StartId      = 0x55AA;
    variablePack.variableHeader.Attributes = (NVARHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY) ? 0x03:0x07;
    variablePack.variableHeader.NameSize   = strlen(NVARHeader->Name) + 1;
    variablePack.variableHeader.DataSize   = NVARHeader->Size - variablePack.variableHeader.NameSize - sizeof(NVAR_ENTRY_HEADER);
    variablePack.variableHeader.State = 0x3F;
    variablePack.variableHeader.VendorGuid = GuidToString(*guid);

    /* 如果之前var容器中已存在，则证明该Var变量已创建不需要再修改默认值了 */
    if (findVarPack(NVARHeader->Name, variablePackages, variablePack.variableHeader.VendorGuid))
    {
        continue;
    }

    variablePack.variable.name.offset = variablePack.offset + offsetof(NVAR_ENTRY_HEADER, Name);
    variablePack.variable.name.size = variablePack.variableHeader.NameSize * 2;
    variablePack.variable.name.name.clear();
    for (uint32_t j = 0; j <  variablePack.variable.name.size/2; j++) {
      variablePack.variable.name.name.push_back(buffer[variablePack.variable.name.offset + j]);
      variablePack.variable.name.name.push_back(0x0);
    }

    variablePack.variable.data.offset = variablePack.variable.name.offset + variablePack.variableHeader.NameSize;
    variablePack.variable.data.size   = variablePack.variableHeader.DataSize;
    if (variablePack.variable.data.size < variablePack.variable.data.data.size()) {
      for (size_t i = 0; i < variablePack.variable.data.size ; i++)
      {
        variablePack.variable.data.data.at(i) = buffer[i + variablePack.variable.data.offset];
      }
    } else {
      cout << "ERR: [" << __FUNCTION__ << "](" << dec << __LINE__ << ") variable data size is over!!!" << endl;
    } 

    variablePackages.push_back(variablePack);
  }


  return;
}

void displayVariableInfo(const vector<EFI_VARIABLE_PACK> &variablePackages) {
  // Display string packages info
  cout << "[" << __FUNCTION__ << "](" << dec << __LINE__ << ") begin." << endl;
  // Go through string packages
  for (uint32_t i = 0; i < variablePackages.size(); i++) {
    // Display string package info
    cout << "\t variablePackages " << i << " data:" << endl;
    cout << "\t\t offset: 0x" << hex << uppercase << setfill('0') << variablePackages[i].offset << endl;
    cout << "\t\t size:   0x" << hex << uppercase << setfill('0') << variablePackages[i].size << endl;
    print_arry(variablePackages[i].data, variablePackages[i].size);
    cout << "\t variablePackage " << i << " Information:" << endl;
    cout << "\t\t StartId:    0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variableHeader.StartId << endl;
    cout << "\t\t State:      0x" << setw(8) << hex << uppercase << setfill('0') << (uint16_t)variablePackages[i].variableHeader.State << endl;
    cout << "\t\t Attributes: 0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variableHeader.Attributes << endl;
    cout << "\t\t NameSize:   0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variableHeader.NameSize << endl;
    cout << "\t\t DataSize:   0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variableHeader.DataSize << endl;
    cout << "\t\t VendorGuid: " << variablePackages[i].variableHeader.VendorGuid << endl;
    cout << "\t variable " << i << " Information:" << endl;
    cout << "\t NAME: " << endl;
    cout << "\t\t NameOffset: 0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variable.name.offset << endl;
    cout << "\t\t NameSize:   0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variable.name.size << endl;
    cout << "\t\t Name:       " << variablePackages[i].variable.name.name << endl;
    cout << "\t DATA: " << endl;
    cout << "\t\t DataOffset: 0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variable.data.offset << endl;
    cout << "\t\t DataSize:   0x" << setw(8) << hex << uppercase << setfill('0') << variablePackages[i].variable.data.size << endl;
    print_arry(variablePackages[i].variable.data.data, variablePackages[i].variable.data.size);
  }
  cout << endl;
}


